package com.etone.smartAudit.service;

import com.etone.smartAudit.domain.Admin;
import com.etone.smartAudit.domain.AuditRisk;
import com.etone.smartAudit.domain.AuditRiskHistory;
import com.etone.smartAudit.dto.auditRisk.AuditRiskCheckDTO;
import com.etone.smartAudit.dto.auditRisk.AuditRiskDTO;
import com.etone.smartAudit.dto.task.ItemTaskDTO;
import com.etone.smartAudit.enums.CheckState;
import com.etone.smartAudit.enums.TaskType;
import com.etone.smartAudit.error.CustomParameterizedException;
import com.etone.smartAudit.mapper.AuditRiskHistoryMapper;
import com.etone.smartAudit.mapper.AuditRiskMapper;
import com.etone.smartAudit.mapstruct.AuditRiskMapstruct;
import com.etone.smartAudit.utils.ArraysExtendUtil;
import com.etone.smartAudit.vo.FileVO;
import com.etone.smartAudit.vo.PagerVO;
import com.etone.smartAudit.vo.auditRisk.AuditRiskDetailVO;
import com.etone.smartAudit.vo.auditRisk.AuditRiskHistoryListVO;
import com.etone.smartAudit.vo.auditRisk.AuditRiskListVO;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: 蒋学伟
 * @create: 2020-06-17 18:17:01
 * @Description
 */
@Service
public class AuditRiskService {

    @Autowired
    private AuditRiskMapper auditRiskMapper;

    @Autowired
    private AuditRiskMapstruct auditRiskMapstruct;

    @Autowired
    private AuditRiskHistoryMapper auditRiskHistoryMapper;

    @Autowired
    private TaskService taskService;

    @Autowired
    private FileUploadService fileUploadService;

    /**
     * 审计风险列表
     *
     * @param key
     * @param level1
     * @param level2
     * @param startUpdateTime
     * @param endUpdateTime
     * @param page
     * @param pageSize
     * @return
     */
    public PagerVO<AuditRiskListVO> list(String key, String level1, String level2, Date startUpdateTime, Date endUpdateTime, int page, int pageSize) {
        Page<AuditRiskListVO> auditRiskListVOS = PageHelper.startPage(page, pageSize).doSelectPage(() -> {
            auditRiskMapper.findList(key, level1, level2, startUpdateTime, endUpdateTime);
        });
        return PagerVO.of(auditRiskListVOS);
    }

    /**
     * 查询历史记录
     *
     * @param auditRiskId
     * @param page
     * @param pageSize
     * @return
     */
    public PagerVO<AuditRiskHistoryListVO> findAuditRiskHistoryList(Integer auditRiskId, int page, int pageSize) {
        Page<AuditRiskHistoryListVO> auditRiskHistoryPage = PageHelper.startPage(page, pageSize).doSelectPage(() -> {
            auditRiskMapper.findAuditRiskHistoryList(auditRiskId);
        });
        return PagerVO.of(auditRiskHistoryPage);
    }

    public AuditRisk get(Integer id) {
        AuditRisk auditRisk = auditRiskMapper.selectById(id);
        if (auditRisk == null) {
            throw new CustomParameterizedException("审计风险不存在");
        }
        return auditRisk;
    }

    /**
     * 编辑｜新增
     *
     * @param id
     * @param auditRiskDTO
     * @param admin
     */
    @Transactional(rollbackFor = Exception.class)
    public void save(Integer id, AuditRiskDTO auditRiskDTO, Admin admin) {
        AuditRisk auditRisk;
        Date now = new Date();
        if (id == null) {
            auditRisk = AuditRisk
                    .builder()
                    .createTime(now)
                    .build();
        } else {
            auditRisk = get(id);
            //审核中无法编辑
            if (auditRisk.getState() == CheckState.CHECKING) {
                throw new CustomParameterizedException("审核中，无法编辑");
            }
        }

        //旧文件
        List<FileVO> oldModuleFiles = auditRisk.getModuleFiles();
        List<FileVO> oldProcessAssetFiles = auditRisk.getProcessAssetFiles();

        auditRiskMapstruct.copyToAuditRisk(auditRisk, auditRiskDTO);
        auditRisk.setCheckTime(null);
        auditRisk.setUpdateTime(now);
        auditRisk.setState(CheckState.CHECKING);

        if (id == null) {
            auditRiskMapper.insert(auditRisk);
        } else {
            auditRiskMapper.updateById(auditRisk);
        }

        //添加到任务审核中去
        taskService.add(
                ItemTaskDTO
                        .builder()
                        .name(auditRisk.getDoubts())
                        .nodeAdminId(auditRisk.getNodeAdminId())
                        .nodeAdminName(auditRisk.getNodeAdminName())
                        .info(auditRisk)
                        .itemTypeId(auditRisk.getId())
                        .build(),
                admin,
                TaskType.ITEM_RISK);

        //清理临时文件
        fileUploadService.deleteFileForUpdate(
                ArraysExtendUtil.mergerArraysList(auditRiskDTO.getModuleFiles(), auditRiskDTO.getProcessAssetFiles()),
                ArraysExtendUtil.mergerArraysList(oldModuleFiles, oldProcessAssetFiles)
        );

    }

    /**
     * 获取 AuditRiskDetailVO
     *
     * @param id
     * @return
     */
    public AuditRiskDetailVO getAuditRiskDetailVO(Integer id) {
        AuditRisk auditRisk = get(id);
        AuditRiskDetailVO auditRiskDetailVO = auditRiskMapstruct.getAuditRiskDetailVO(auditRisk);
        return auditRiskDetailVO;
    }

    /**
     * 删除风险审计
     *
     * @param id
     * @param loginAdmin
     */
    @Transactional(rollbackFor = Exception.class)
    public void delete(Integer id, Admin loginAdmin) {
        AuditRisk auditRisk = get(id);
        int count = auditRiskMapper.deleteById(id);
        if (count == 0) {
            throw new CustomParameterizedException("该记录不存在，删除失败");
        }

        doAfterDelete(Arrays.asList(id), auditRisk.getAllFiles());
    }

    /**
     * 批量删除风险审计
     *
     * @param ids
     * @param loginAdmin
     */
    @Transactional(rollbackFor = Exception.class)
    public void delete(List<Integer> ids, Admin loginAdmin) {
        List<AuditRisk> auditRisks = auditRiskMapper.selectBatchIds(ids);
        int count = auditRiskMapper.deleteBatchIds(ids);
        if (count == 0) {
            throw new CustomParameterizedException("记录不存在，删除失败");
        }

        List<FileVO> files = auditRisks.stream().map(auditRisk -> auditRisk.getAllFiles()).flatMap(fileVOS -> fileVOS.stream()).collect(Collectors.toList());
        doAfterDelete(ids, files);
    }

    /**
     * 删除之后的操作
     *
     * @param ids
     * @param fileVOS
     */
    private void doAfterDelete(List<Integer> ids, List<FileVO> fileVOS) {

        //删除审计风险历史记录
        deleteHistoryByAuditRiskId(ids);

        //删除审计审核任务
        taskService.deleteByItemTypeId(ids, TaskType.ITEM_RISK);

        //删除图片文件
        if (!CollectionUtils.isEmpty(fileVOS)) {
            fileUploadService.deleteFileByFileVO(fileVOS, true, false);
        }
    }

    /**
     * 批量删除审计风险历史记录
     *
     * @param auditRiskIds
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteHistoryByAuditRiskId(List<Integer> auditRiskIds) {
        int count = auditRiskHistoryMapper.deleteByAuditRiskId(auditRiskIds);
    }

    /**
     * 风险审计审核
     *
     * @param id
     * @param auditRiskCheckDTO
     */
    @Transactional(rollbackFor = Exception.class)
    public void check(Integer id, AuditRiskCheckDTO auditRiskCheckDTO) {
        AuditRisk auditRisk = get(id);
        Date now = new Date();
        if (!auditRisk.getState().equals(CheckState.CHECKING)) {
            throw new CustomParameterizedException("审计非审核状态，无法审核");
        }
        switch (auditRiskCheckDTO.getState()) {
            case PASS:
                auditRisk.setState(CheckState.PASS);
                auditRisk.setCheckTime(now);
                auditRisk.setUpdateTime(now);

                //插入历史记录
                AuditRiskHistory auditRiskHistory = auditRiskMapstruct.getAuditRiskHistory(auditRisk);
                auditRiskHistory.setId(null);
                auditRiskHistory.setAuditRiskId(auditRisk.getId());
                auditRiskHistoryMapper.insert(auditRiskHistory);
                break;
            case REJECT:
                auditRisk.setUpdateTime(now);
                auditRisk.setState(CheckState.REJECT);
                break;
            default:
                throw new CustomParameterizedException("审核状态异常");
        }

        auditRiskMapper.updateById(auditRisk);
    }
}
